package com.allm.ai.common.service;

import com.allm.ai.common.entity.AiModel;
import com.allm.ai.common.factory.ChatModelFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * ChatModel 和 ChatClient 缓存管理服务
 * 基于数据库中的 AiModel 配置动态创建和缓存 ChatModel/ChatClient
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ChatModelCacheService {
    
    private final ChatMemory chatMemory;
    private final ChatModelFactory chatModelFactory;
    
    // 缓存项包装类，包含创建时间和访问时间
    public static class CacheItem<T> {
        private final T item;
        private final LocalDateTime createdAt;
        private volatile LocalDateTime lastAccessedAt;
        
        public CacheItem(T item) {
            this.item = item;
            this.createdAt = LocalDateTime.now();
            this.lastAccessedAt = LocalDateTime.now();
        }
        
        public T getItem() {
            this.lastAccessedAt = LocalDateTime.now();
            return item;
        }
        
        public LocalDateTime getCreatedAt() { return createdAt; }
        public LocalDateTime getLastAccessedAt() { return lastAccessedAt; }
    }
    
    // ChatModel 缓存 - 基于 AiModel 配置创建
    private final Map<String, CacheItem<ChatModel>> chatModelCache = new ConcurrentHashMap<>();
    
    // ChatClient 缓存
    private final Map<String, CacheItem<ChatClient>> chatClientCache = new ConcurrentHashMap<>();
    
    // 缓存配置
    private static final long CACHE_TTL_HOURS = 24; // 缓存有效期24小时
    private static final int MAX_CACHE_SIZE = 100; // 最大缓存数量
    
    /**
     * 生成缓存键
     */
    public String generateCacheKey(AiModel model) {
        return String.format("%s_%s_%s_%s_%s_%s", 
            model.getServiceProvider(),
            model.getApiEndpoint(),
            model.getName(),
            model.getTemperature(),
            model.getMaxTokens(),
            Objects.hashCode(model.getApiKey())
        );
    }
    
    /**
     * 获取或创建 ChatModel
     * 根据 AiModel 配置动态创建
     */
    public ChatModel getOrCreateChatModel(AiModel aiModel) {
        String cacheKey = generateCacheKey(aiModel);
        
        CacheItem<ChatModel> cachedItem = chatModelCache.get(cacheKey);
        if (cachedItem != null) {
            log.debug("从缓存获取 ChatModel: {} (提供商: {})", aiModel.getName(), aiModel.getServiceProvider());
            return cachedItem.getItem();
        }
        
        // 检查缓存大小
        if (chatModelCache.size() >= MAX_CACHE_SIZE) {
            cleanOldestEntries(chatModelCache, MAX_CACHE_SIZE / 2);
        }
        
        log.info("创建新的 ChatModel: {} (提供商: {})", aiModel.getName(), aiModel.getServiceProvider());
        
        try {
            // 使用工厂创建 ChatModel
            ChatModel chatModel = chatModelFactory.createChatModel(aiModel);
            chatModelCache.put(cacheKey, new CacheItem<>(chatModel));
            return chatModel;
        } catch (Exception e) {
            log.error("创建 ChatModel 失败: {} (提供商: {})", aiModel.getName(), aiModel.getServiceProvider(), e);
            throw new RuntimeException("创建 ChatModel 失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 获取或创建 ChatClient（带会话记忆）
     */
    public ChatClient getOrCreateChatClient(AiModel aiModel) {
        String cacheKey = generateCacheKey(aiModel) + "_with_memory";
        
        CacheItem<ChatClient> cachedItem = chatClientCache.get(cacheKey);
        if (cachedItem != null) {
            log.debug("从缓存获取 ChatClient: {}", aiModel.getName());
            return cachedItem.getItem();
        }
        
        // 检查缓存大小
        if (chatClientCache.size() >= MAX_CACHE_SIZE) {
            cleanOldestEntries(chatClientCache, MAX_CACHE_SIZE / 2);
        }
        
        log.info("创建新的 ChatClient (带记忆): {}", aiModel.getName());
        
        try {
            ChatModel chatModel = getOrCreateChatModel(aiModel);
            
            ChatClient chatClient = ChatClient.builder(chatModel)
                    .defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
                    .build();
            
            chatClientCache.put(cacheKey, new CacheItem<>(chatClient));
            return chatClient;
        } catch (Exception e) {
            log.error("创建 ChatClient 失败: {}", aiModel.getName(), e);
            throw new RuntimeException("创建 ChatClient 失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 获取或创建简单的 ChatClient（无会话记忆）
     */
    public ChatClient getOrCreateSimpleChatClient(AiModel aiModel) {
        String cacheKey = generateCacheKey(aiModel) + "_simple";
        
        CacheItem<ChatClient> cachedItem = chatClientCache.get(cacheKey);
        if (cachedItem != null) {
            log.debug("从缓存获取简单 ChatClient: {}", aiModel.getName());
            return cachedItem.getItem();
        }
        
        log.info("创建新的简单 ChatClient: {}", aiModel.getName());
        
        try {
            ChatModel chatModel = getOrCreateChatModel(aiModel);
            ChatClient chatClient = ChatClient.create(chatModel);
            
            chatClientCache.put(cacheKey, new CacheItem<>(chatClient));
            return chatClient;
        } catch (Exception e) {
            log.error("创建简单 ChatClient 失败: {}", aiModel.getName(), e);
            throw new RuntimeException("创建简单 ChatClient 失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 检查是否支持创建 ChatModel
     */
    public boolean canCreateChatModel(AiModel aiModel) {
        return chatModelFactory.supportsProvider(aiModel.getServiceProvider());
    }
    
    /**
     * 检查模型是否支持流式输出
     */
    public boolean supportsStreaming(AiModel aiModel) {
        return chatModelFactory.supportsStreaming(aiModel);
    }
    
    /**
     * 清理最旧的缓存条目
     */
    private <T> void cleanOldestEntries(Map<String, CacheItem<T>> cache, int keepCount) {
        if (cache.size() <= keepCount) {
            return;
        }
        
        List<Map.Entry<String, CacheItem<T>>> entries = new ArrayList<>(cache.entrySet());
        entries.sort((a, b) -> a.getValue().getLastAccessedAt().compareTo(b.getValue().getLastAccessedAt()));
        
        int removeCount = cache.size() - keepCount;
        for (int i = 0; i < removeCount; i++) {
            String key = entries.get(i).getKey();
            cache.remove(key);
            log.debug("清理旧缓存条目: {}", key);
        }
        
        log.info("清理了 {} 个旧缓存条目，当前缓存大小: {}", removeCount, cache.size());
    }
    
    /**
     * 清理过期的缓存条目
     */
    @Scheduled(fixedRate = 3600000) // 每小时执行一次
    public void cleanExpiredCache() {
        LocalDateTime expireTime = LocalDateTime.now().minusHours(CACHE_TTL_HOURS);
        
        int removedChatModels = cleanExpiredEntries(chatModelCache, expireTime);
        int removedChatClients = cleanExpiredEntries(chatClientCache, expireTime);
        
        if (removedChatModels > 0 || removedChatClients > 0) {
            log.info("定期清理过期缓存: ChatModel={}, ChatClient={}", removedChatModels, removedChatClients);
        }
    }
    
    /**
     * 清理过期条目的通用方法
     */
    private <T> int cleanExpiredEntries(Map<String, CacheItem<T>> cache, LocalDateTime expireTime) {
        int removedCount = 0;
        Iterator<Map.Entry<String, CacheItem<T>>> iterator = cache.entrySet().iterator();
        
        while (iterator.hasNext()) {
            Map.Entry<String, CacheItem<T>> entry = iterator.next();
            if (entry.getValue().getLastAccessedAt().isBefore(expireTime)) {
                iterator.remove();
                removedCount++;
                log.debug("移除过期缓存条目: {}", entry.getKey());
            }
        }
        
        return removedCount;
    }
    
    /**
     * 清理所有缓存
     */
    public void clearAllCache() {
        int chatModelCount = chatModelCache.size();
        int chatClientCount = chatClientCache.size();
        
        chatModelCache.clear();
        chatClientCache.clear();
        
        log.info("清理所有缓存: ChatModel={}, ChatClient={}", chatModelCount, chatClientCount);
    }
    
    /**
     * 清理特定模型的缓存
     */
    public void clearCache(AiModel aiModel) {
        String baseKey = generateCacheKey(aiModel);
        
        chatModelCache.remove(baseKey);
        chatClientCache.remove(baseKey + "_with_memory");
        chatClientCache.remove(baseKey + "_simple");
        
        log.info("清理特定模型缓存: {}", aiModel.getName());
    }
    
    /**
     * 获取缓存统计信息
     */
    public Map<String, Object> getCacheStats() {
        Map<String, Object> stats = new HashMap<>();
        
        stats.put("chatModelCacheSize", chatModelCache.size());
        stats.put("chatClientCacheSize", chatClientCache.size());
        stats.put("maxCacheSize", MAX_CACHE_SIZE);
        stats.put("cacheTtlHours", CACHE_TTL_HOURS);
        
        // 工厂统计信息
        stats.put("factoryStats", chatModelFactory.getCreatorStats());
        
        // 详细统计
        Map<String, Object> chatModelStats = new HashMap<>();
        chatModelStats.put("totalCount", chatModelCache.size());
        chatModelStats.put("keys", new ArrayList<>(chatModelCache.keySet()));
        
        Map<String, Object> chatClientStats = new HashMap<>();
        chatClientStats.put("totalCount", chatClientCache.size());
        chatClientStats.put("keys", new ArrayList<>(chatClientCache.keySet()));
        
        stats.put("chatModelDetails", chatModelStats);
        stats.put("chatClientDetails", chatClientStats);
        
        return stats;
    }
    
    /**
     * 获取缓存健康状态
     */
    public Map<String, Object> getHealthStatus() {
        Map<String, Object> health = new HashMap<>();
        
        double chatModelUsage = (double) chatModelCache.size() / MAX_CACHE_SIZE;
        double chatClientUsage = (double) chatClientCache.size() / MAX_CACHE_SIZE;
        
        // 检查工厂状态
        List<String> supportedProviders = chatModelFactory.getSupportedProviders();
        boolean hasCreators = !supportedProviders.isEmpty();
        
        String status = "HEALTHY";
        if (chatModelUsage > 0.8 || chatClientUsage > 0.8) {
            status = "WARNING";
        } else if (!hasCreators) {
            status = "NO_CREATORS";
        }
        
        health.put("status", status);
        health.put("chatModelUsage", String.format("%.1f%%", chatModelUsage * 100));
        health.put("chatClientUsage", String.format("%.1f%%", chatClientUsage * 100));
        health.put("hasCreators", hasCreators);
        health.put("supportedProviders", supportedProviders);
        health.put("timestamp", LocalDateTime.now());
        
        return health;
    }
} 